package com.example.erp;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletResponse;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/chatclient")
public class ChatController {

	private final ChatClient chatClient;
	private final int MAX_MESSAGES = 100;
    private final InMemoryChatMemoryRepository chatMemoryRepository = new InMemoryChatMemoryRepository();
    private final MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.builder()
            .chatMemoryRepository(chatMemoryRepository)
            .maxMessages(MAX_MESSAGES)
            .build();

	// 构造注入初始化 chatClient 实例
	public ChatController(ChatClient.Builder chatClientBuilder, ToolCallbackProvider toolCallbackProviders) {
		// 使用ChatClient构建器配置并初始化ChatClient实例
		this.chatClient = chatClientBuilder
				.defaultAdvisors(MessageChatMemoryAdvisor.builder(messageWindowChatMemory).build())
				// 设置默认的工具集
				.defaultTools(toolCallbackProviders)
				// 设置默认的选项配置，此处使用了Top-P采样策略，以增加响应的多样性
				// .defaultOptions(DashScopeChatOptions.builder().withTopP(0.7).build())
				// 最终构建ChatClient实例
				.build();
	}

	@GetMapping(value = "/generate_stream")
	public Flux<ChatResponse> generateStream(HttpServletResponse response, String id, String prompt) {
		response.setCharacterEncoding("UTF-8");
		// 原来的写法，在spring ai 1.0.0 中废弃，InMemoryChatMemory 在chatClient构造时设置
		// 创建一个MessageChatMemoryAdvisor实例，用于管理聊天记忆，限制最多10条消息
		// 这里的chatMemory和id是假设已经存在的变量，用于初始化顾问对象
//		var messageChatMemoryAdvisor = new MessageChatMemoryAdvisor(chatMemory, id, 10);
//		return this.chatClient.prompt(prompt).advisors(messageChatMemoryAdvisor).stream().chatResponse();
		
		// spring ai 1.0.0 中新写法
		return this.chatClient.prompt(prompt).advisors(advisor -> advisor.param(CONVERSATION_ID, id)).stream().chatResponse();
	}

	@GetMapping("/advisor/chat/{id}/{prompt}")
	public Flux<String> advisorChat(HttpServletResponse response, @PathVariable String id, @PathVariable String prompt) {
		// 设置响应内容的字符编码为UTF-8，以确保多语言支持和字符显示正确
		response.setCharacterEncoding("UTF-8");

		// 创建一个MessageChatMemoryAdvisor实例，用于管理聊天记忆，限制最多10条消息
		// 这里的chatMemory和id是假设已经存在的变量，用于初始化顾问对象
//		var messageChatMemoryAdvisor = new MessageChatMemoryAdvisor(chatMemory, id, 10);

		// 使用chatClient的prompt方法发起聊天请求，并传入prompt作为提示信息
		// 这里的prompt是一个变量，代表用户或系统输入的提示信息
		// .advisors方法用于添加聊天顾问，本例中添加了之前创建的messageChatMemoryAdvisor
		// .stream().content()用于获取聊天响应的内容流
		// 这个方法的返回值是聊天响应的内容，经过顾问处理后以流的形式返回
		return this.chatClient.prompt(prompt).advisors(advisor -> advisor.param(CONVERSATION_ID, id)).stream().content();
	}

}
